﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WooCoo.Tools
{
    public static class UriHelper
    {
        #region Tag
        /// <summary>forwardslash character</summary>
        public const char FORWARDSLASH = '/';

        /// <summary>leftparan character</summary>
        public const char LEFTPAREN = '(';

        /// <summary>rightparan character</summary>
        public const char RIGHTPAREN = ')';

        /// <summary>questionmark character</summary>
        public const char QUESTIONMARK = '?';

        /// <summary>ampersand character</summary>
        public const char AMPERSAND = '&';

        /// <summary>equals character</summary>
        public const char EQUALSSIGN = '=';

        /// <summary>at sign</summary>
        public const char ATSIGN = '@';

        /// <summary>dollar sign character</summary>
        public const char DOLLARSIGN = '$';

        /// <summary>space</summary>
        public const char SPACE = ' ';

        /// <summary>comma</summary>
        public const char COMMA = ',';

        /// <summary>colon</summary>
        public const char COLON = ':';

        /// <summary> semicolon </summary>
        public const char SEMICOLON = ';';

        /// <summary>single quote</summary>
        public const char QUOTE = '\'';

        /// <summary>asterisk</summary>
        public const char ASTERISK = '*';

        /// <summary>top</summary>
        public const string OPTIONTOP = "top";

        /// <summary>skip</summary>
        public const string OPTIONSKIP = "skip";

        /// <summary>orderby</summary>
        public const string OPTIONORDERBY = "orderby";

        /// <summary>where</summary>
        public const string OPTIONFILTER = "filter";

        /// <summary>desc</summary>
        public const string OPTIONDESC = "desc";

        /// <summary>expand</summary>
        public const string OPTIONEXPAND = "expand";

        /// <summary>count</summary>
        public const string OPTIONCOUNT = "count";

        /// <summary>select</summary>
        public const string OPTIONSELECT = "select";

        /// <summary>The $format query option.</summary>
        public const string OPTIONFORMAT = "format";

        /// <summary>true</summary>
        public const string COUNTTRUE = "true";

        /// <summary>value</summary>
        public const string COUNT = "count";

        /// <summary>and</summary>
        public const string AND = "and";

        /// <summary>or</summary>
        public const string OR = "or";

        /// <summary>eq</summary>
        public const string EQ = "eq";

        /// <summary>ne</summary>
        public const string NE = "ne";

        /// <summary>lt</summary>
        public const string LT = "lt";

        /// <summary>le</summary>
        public const string LE = "le";

        /// <summary>gt</summary>
        public const string GT = "gt";

        /// <summary>ge</summary>
        public const string GE = "ge";

        /// <summary>add</summary>
        public const string ADD = "add";

        /// <summary>sub</summary>
        public const string SUB = "sub";

        /// <summary>mul</summary>
        public const string MUL = "mul";

        /// <summary>div</summary>
        public const string DIV = "div";

        /// <summary>mod</summary>
        public const string MOD = "mod";

        /// <summary>negate</summary>
        public const string NEGATE = "-";

        /// <summary>not</summary>
        public const string NOT = "not";

        /// <summary>null</summary>
        public const string NULL = "null";

        /// <summary>isof</summary>
        public const string ISOF = "isof";

        /// <summary>cast</summary>
        public const string CAST = "cast";

        /// <summary>forward slash char array for triming uris</summary>
        public static readonly char[] ForwardSlash = new char[]
		{
			'/'
		};
        #endregion

        /// <summary>
        /// Turn Uri instance into string representation
        /// This is needed because Uri.ToString unescapes the string
        /// </summary>
        /// <param name="uri">The uri instance</param>
        /// <returns>The string representation of the uri</returns>
        public static string UriToString(Uri uri)
        {
            if (!uri.IsAbsoluteUri)
            {
                return uri.OriginalString;
            }
            return uri.AbsoluteUri;
        }
        /// <summary>new Uri(string uriString, UriKind uriKind)</summary>
        /// <param name="value">value</param>
        /// <param name="kind">kind</param>
        /// <returns>new Uri(value, kind)</returns>
        public static Uri CreateUri(string value, UriKind kind)
        {
            if (value != null)
            {
                return new Uri(value, kind);
            }
            return null;
        }
        /// <summary>new Uri(Uri baseUri, Uri requestUri)</summary>
        /// <param name="baseUri">baseUri</param>
        /// <param name="requestUri">relativeUri</param>
        /// <returns>new Uri(baseUri, requestUri)</returns>
        public static Uri CreateUri(Uri baseUri, Uri requestUri)
        {
            Check.CheckArgumentNull<Uri>(requestUri, "requestUri");
            if (!baseUri.IsAbsoluteUri)
            {
                return UriHelper.CreateUri(UriHelper.UriToString(baseUri) + '/' + UriHelper.UriToString(requestUri), UriKind.Relative);
            }
            if (requestUri.IsAbsoluteUri)
            {
                return requestUri;
            }
            return UriHelper.AppendBaseUriAndRelativeUri(baseUri, requestUri);
        }
        /// <summary>
        /// Appends the absolute baseUri with the relativeUri to create a new absolute uri
        /// </summary>
        /// <param name="baseUri">An absolute Uri</param>
        /// <param name="relativeUri">A relative Uri</param>
        /// <returns>An absolute Uri that is the combination of the base and relative Uris passed in.</returns>
        private static Uri AppendBaseUriAndRelativeUri(Uri baseUri, Uri relativeUri)
        {
            string text = UriHelper.UriToString(baseUri);
            string text2 = UriHelper.UriToString(relativeUri);
            if (text.EndsWith("/", StringComparison.Ordinal))
            {
                if (text2.StartsWith("/", StringComparison.Ordinal))
                {
                    relativeUri = new Uri(baseUri, UriHelper.CreateUri(text2.TrimStart(UriHelper.ForwardSlash), UriKind.Relative));
                }
                else
                {
                    relativeUri = new Uri(baseUri, relativeUri);
                }
            }
            else
            {
                relativeUri = UriHelper.CreateUri(text + "/" + text2.TrimStart(UriHelper.ForwardSlash), UriKind.Absolute);
            }
            return relativeUri;
        }
    }
}
